package com.zrrd.network.chatRoom;

import java.io.*;
import java.net.Socket;
import java.util.List;

/**
 * @author WanJl
 * @version 1.0
 * @title ThreadSocket
 * @description 是处理来自客户端发送消息，并且转发给其他客户端
 * 由服务器来进行调用。
 * @create 2023/11/4 17:18
 */
public class ClientHandler implements Runnable{

    private Socket socket;
    private List<PrintWriter> list;

    public ClientHandler(Socket socket, List<PrintWriter> list) {
        this.socket = socket;
        this.list = list;
    }

    @Override
    public void run() {
        PrintWriter pw =null;
        String username=null;
        try{
            //1、用户登录---其实就是客户端连接服务器成功之后需要先输入自己的用户名
            //1.1获取socket的输入流，其实就是接收用户上线后输入的自己的【用户名信息】。
            InputStream in = socket.getInputStream();
            //1.2 处理--转换成字符流
            InputStreamReader isr = new InputStreamReader(in,"UTF-8");
            //1.3 处理--缓冲字符流
            BufferedReader br = new BufferedReader(isr);

            //2、服务器要把用户上线的消息【用户名信息】发送给所有的客户端
            username = br.readLine();
            String onlineMsg=username+"上线了....";
            //调用发送消息到所有客户端的方法。
            sendMessage(onlineMsg);

            //3、获取客户端的输出流，并且把流存入list集合
            OutputStream out = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(out, "UTF-8");
            pw = new PrintWriter(osw, true);

            //把pw流对象（其实就是在线的用户。因为只有在线的用户才能产生输出流往出发消息。）
            add(pw);

            //4、不断的把客户端发过来的消息，转发给所有客户端
            String message=null;
            while ((message=br.readLine())!=null){
                sendMessage(username+"说："+message);
            }


        }catch (Exception e){
            //e.printStackTrace();
        }finally {
            //5、客户端和服务器断开连接的操作
            remove(pw);
            //6、通知其他客户端，当前客户端下线了
            sendMessage(username+"下线了....");
            //7、关闭socket
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    /**
     * 将下线的客户端移除list集合（在线列表）
     * @param pw
     */
    private void remove(PrintWriter pw) {
        list.remove(pw);
    }

    /**
     * 把能够发送消息的客户端的输出流放入到list集合（在线列表）
     * @param pw
     */
    private void add(PrintWriter pw) {
        list.add(pw);
    }

    /**
     * 发送消息
     * @param onlineMsg
     */
    private void sendMessage(String onlineMsg) {

        for (int i = 0; i < list.size(); i++) {
            PrintWriter out = list.get(i);
            out.println(onlineMsg);
        }
    }
}
